import datetime
from django.db import models
from core.yl.client import YLClient, ProgramPay, yl_app_pay

yl_client = YLClient()
yl_program_pay = ProgramPay()


class YLPayRecordManager(models.Manager):
    def create_record(self, totalAmount, merOrderId, srcReserve="", pay_type=1):
        return self.create(
            totalAmount=totalAmount,
            out_trade_no=merOrderId,
            srcReserve=srcReserve,
            pay_type=pay_type
        )


class YLPayRecord(models.Model):
    """
    银联支付记录
    """
    payType = ((1, "银联商务公众号支付(H5链接跳转)",), (2, "微信",), (3, "支付宝",), (4, "云闪付",),)
    pay_type = models.IntegerField(verbose_name="支付类型", default=1, choices=payType)
    payTime = models.DateTimeField(verbose_name="支付完成时间", blank=True, null=True)
    totalAmount = models.IntegerField(verbose_name="订单金额", blank=True, null=True, help_text="以分为单位")
    createTime = models.DateTimeField(verbose_name="创建时间", auto_now_add=True)
    out_trade_no = models.CharField(verbose_name="商户订单号, 对应SupplyOrder.out_trade_no", db_index=True, max_length=64)
    srcReserve = models.CharField(verbose_name="附加信息", blank=True, null=True, max_length=64)

    connectSys = models.CharField(verbose_name="链接系统", blank=True, null=True, max_length=128)
    invoiceAmount = models.IntegerField(verbose_name="开票金额", blank=True, null=True, help_text="以分为单位")
    buyerPayAmount = models.IntegerField(verbose_name="买家付款金额", blank=True, null=True, help_text="以分为单位")
    billFunds = models.CharField(verbose_name="资金渠道", blank=True, null=True, max_length=128)
    buyerId = models.CharField(verbose_name="卖家id", blank=True, null=True, max_length=128)
    targetOrderId = models.CharField(verbose_name="目标平台单号", blank=True, null=True, max_length=128)
    notifyId = models.CharField(verbose_name="通知唯一id，重发通知不变", blank=True, null=True, max_length=128)
    orderDesc = models.CharField(verbose_name="订单描述", blank=True, null=True, max_length=128)
    seqId = models.CharField(verbose_name="平台流水号", blank=True, null=True, max_length=128, help_text="平台流水号")
    status = models.CharField(verbose_name="交易状态", db_index=True, max_length=64)
    targetSys = models.CharField(verbose_name="目标平台代码", db_index=True, max_length=64)
    url = models.CharField(verbose_name="前端跳转url", max_length=512, blank=True, null=True)
    is_pay = models.BooleanField(verbose_name="是否支付", default=False)
    objects = YLPayRecordManager()

    class Meta:
        verbose_name = "通联交易记录"
        verbose_name_plural = verbose_name

    def update_record(self, data):
        if data.get("connectSys"):
            self.connectSys = data.get("connectSys")
        if data.get("invoiceAmount"):
            self.invoiceAmount = data.get("invoiceAmount")
        if data.get("buyerPayAmount"):
            self.buyerPayAmount = data.get("buyerPayAmount")
        if data.get("billFunds"):
            self.billFunds = data.get("billFunds")
        if data.get("buyerId"):
            self.buyerId = data.get("buyerId")
        if data.get("targetOrderId"):
            self.targetOrderId = data.get("targetOrderId")
        if data.get("notifyId"):
            self.notifyId = data.get("notifyId")
        if data.get("orderDesc"):
            self.orderDesc = data.get("orderDesc")
        if data.get("seqId"):
            self.seqId = data.get("seqId")
        if data.get("targetSys"):
            self.targetSys = data.get("targetSys")
        if data.get("status"):
            self.status = data.get("status")
            if self.status == "TRADE_SUCCESS":
                self.is_pay = True
        self.save()


class YLRefundRecordManager(models.Manager):
    def create_refund(self, **kwargs):
        data = dict()

        data["srcReserve"] = kwargs.get("srcReserve")
        data["refundAmount"] = kwargs.get("refundAmount")
        data["orderDatetime"] = kwargs.get("orderDatetime")
        data["mchtRefundOrderNo"] = kwargs.get("mchtRefundOrderNo")
        data["pay_record"] = kwargs.get("pay_record")
        instance = self.create(**data)
        return instance

    def yl_refund(self, refund_amount, out_trade_no, refundOrderId=None, pay_type=4):
        """
        银联退款
        :param refund_amount: 退款金额
        :param pay_record_obj: 支付对象
        :param refundOrderId: 退款订单号
        :return:
        """
        pay_instance = YLPayRecord.objects.get(out_trade_no=out_trade_no)
        if not refundOrderId:
            refundOrderId = yl_client.new_unique_value
        if not refund_amount:
            refund_amount = pay_instance.totalAmount
        merOrderId = pay_instance.out_trade_no
        srcReserve = ""
        now_time = datetime.datetime.now()
        data = {
            "srcReserve": srcReserve,
            "refundAmount": refund_amount,
            "orderDatetime": now_time,
            "mchtRefundOrderNo": refundOrderId,
            "pay_record": pay_instance
        }
        instance = self.create_refund(**data)
        if pay_type == 4:
            response = yl_client.refund(merOrderId, refund_amount, refundOrderId, now_time)
        else:
            response = yl_app_pay.refund(merOrderId, refund_amount, refundOrderId, now_time)
        print(response, "response")
        if response.get("refundStatus") == "SUCCESS":
            instance.update_refund(response)
            return True, "OK"
        else:
            return False, response.get("errMsg")


class YLRefundRecord(models.Model):
    """
    银联退款记录
    """
    srcReserve = models.CharField(max_length=128, blank=True, null=True, verbose_name="预留字段")
    refundAmount = models.IntegerField(verbose_name="退款金额", help_text="以分为单位", blank=True, null=True)
    orderDatetime = models.DateTimeField(verbose_name="提交退款时间")
    mchtRefundOrderNo = models.CharField(max_length=28, verbose_name="商户退款订单号", blank=True, null=True)
    out_refund_no = models.CharField(max_length=28, verbose_name="商户退款订单号（对应订单退款表）", blank=True, null=True)
    error_msg = models.CharField(max_length=128, blank=True, null=True, verbose_name="错误信息")
    error_code = models.CharField(max_length=8, blank=True, null=True, verbose_name="错误代码")
    refundDatetime = models.DateTimeField(verbose_name="退款受理时间", blank=True, null=True)
    refundStatus = models.CharField(verbose_name="受理状态", max_length=14, default="FAIL")

    pay_record = models.ForeignKey("YLPayRecord", verbose_name="对应的支付记录")
    objects = YLRefundRecordManager()

    class Meta:
        verbose_name = "银联退款记录"
        verbose_name_plural = verbose_name

    def update_refund(self, data):
        self.error_msg = data.get("errMsg")
        self.error_code = data.get("errCode")
        self.refundDatetime = data.get("responseTimestamp")
        self.refundStatus = data.get("status")
        self.save()
        return self


class YLProgramRecordManager(models.Manager):
    def create_base(self, kwargs):
        pay_type = kwargs.get("pay_type")
        totalAmount = kwargs.get("totalAmount")
        out_trade_no = kwargs.get("merOrderId")
        srcReserve = kwargs.get("srcReserve")
        ali_user_id = kwargs.get("ali_user_id")
        openid = kwargs.get("openid")
        user = kwargs.get("user")
        requestTimestamp = kwargs.get("requestTimestamp")
        instance = self.create(
            pay_type=pay_type,
            totalAmount=totalAmount,
            out_trade_no=out_trade_no,
            srcReserve=srcReserve,
            ali_user_id=ali_user_id,
            openid=openid,
            requestTimestamp=requestTimestamp,
        )
        # instance = instance.update_response(response)
        return instance


# 小程序支付
class YLProgramRecord(models.Model):
    payType = (("wx.unifiedOrd", "微信小程序",), ("trade.create", "支付宝小程序",),)
    statusDesc = (("NEW_ORDER", "新订单"), ("UNKNOWN", "不明确的交易状态"), ("TRADE_CLOSED", "关闭的交易"),
                  ("WAIT_BUYER_PAY", "等待买家付款"), ("TRADE_SUCCESS", "支付成功"), ("TRADE_REFUND", "订单转入退货流程"))
    pay_type = models.CharField(verbose_name="支付类型", choices=payType, db_index=True, max_length=16)
    totalAmount = models.IntegerField(verbose_name="订单金额", blank=True, null=True, help_text="以分为单位")
    createTime = models.DateTimeField(verbose_name="创建时间", auto_now_add=True)
    requestTimestamp = models.DateTimeField(verbose_name="请求时间")
    out_trade_no = models.CharField(verbose_name="商户订单号, 对应SupplyOrder.out_trade_no", db_index=True, max_length=64)
    srcReserve = models.CharField(verbose_name="附加信息", blank=True, null=True, max_length=64)
    ali_user_id = models.CharField(max_length=32, blank=True, null=True, verbose_name="支付宝userid")
    openid = models.CharField(max_length=32, blank=True, null=True, verbose_name="微信openid")
    # 请求完成后返回数据
    errCode = models.CharField(verbose_name="平台错误码", blank=True, null=True, max_length=256)
    errMsg = models.CharField(verbose_name="平台错误信息", max_length=256, blank=True, null=True)
    msgId = models.CharField(verbose_name="消息ID", max_length=64, blank=True, null=True)
    msgType = models.CharField(verbose_name="消息类型", max_length=64, blank=True, null=True)
    msgSrc = models.CharField(verbose_name="消息来源", max_length=64, blank=True, null=True)
    responseTimestamp = models.DateTimeField(verbose_name="报文响应时间", blank=True, null=True)
    merName = models.CharField(verbose_name="商户名称", max_length=64, blank=True, null=True)
    seqId = models.CharField(verbose_name="平台流水号", max_length=64, blank=True, null=True)
    status = models.CharField(verbose_name="交易状态", max_length=32, blank=True, null=True, db_index=True,
                              choices=statusDesc)
    targetSys = models.CharField(verbose_name="目标平台代码", max_length=32, blank=True, null=True)
    targetMid = models.CharField(verbose_name="支付渠道商户号", max_length=64, blank=True, null=True)
    remark = models.TextField(blank=True, null=True, verbose_name="备注")
    objects = YLProgramRecordManager()

    class Meta:
        verbose_name = "银联小程序支付"
        verbose_name_plural = verbose_name

    def update_response(self, **kwargs):
        """
        按下单请求返回数据更新结果
        :return:
        """
        for k, v in kwargs.items():
            if hasattr(self, k):
                setattr(self, k, v)
        self.save()
        return self


class YLProgramRefundManager(models.Manager):
    def create_base(self, refundAmount, merOrderId, srcReserve="czb"):
        """
        :param refundAmount: 退款金额 以分为单位
        :param merOrderId: 支付时订单号
        :param mchtRefundOrderNo: 退款订单号
        :param srcReserve:
        :return:
        """
        kwargs, response = yl_program_pay.refund(merOrderId, refundAmount)
        instance = self.create(
            refundAmount=kwargs.get("refundAmount"),
            srcReserve=srcReserve,
            orderDatetime=kwargs.get("requestTimestamp"),
            mchtRefundOrderNo=kwargs.get("refundOrderId"),
            merOrderId=merOrderId,
        )
        instance = instance.update_response(response)
        return instance


# 小程序退款
class YLProgramRefund(models.Model):
    # requests
    refundAmount = models.IntegerField(verbose_name="退款金额", help_text="以分为单位")
    srcReserve = models.CharField(verbose_name="请求系统预留字段", max_length=32, blank=True, null=True)
    orderDatetime = models.DateTimeField(verbose_name="申请退款时间")
    mchtRefundOrderNo = models.CharField(max_length=64, verbose_name="商户退款订单号", db_index=True)
    out_refund_no = models.CharField(max_length=24, verbose_name="商户退款订单号（对应订单退款表）", blank=True, null=True)
    merOrderId = models.CharField(max_length=64, verbose_name="支付时的订单号", db_index=True)
    # response
    errCode = models.CharField(verbose_name="平台错误码", blank=True, null=True, max_length=256)
    errMsg = models.CharField(verbose_name="平台错误信息", max_length=256, blank=True, null=True)
    msgType = models.CharField(verbose_name="消息类型", max_length=256, blank=True, null=True)
    status = models.CharField(verbose_name="交易状态", max_length=32, blank=True, null=True, db_index=True,
                              choices=YLProgramRecord.statusDesc)
    targetSys = models.CharField(verbose_name="目标平台代码", max_length=32, blank=True, null=True)

    class Meta:
        verbose_name = "小程序退款"
        verbose_name_plural = verbose_name

    def update_response(self, **kwargs):
        """
        按下单请求返回数据更新结果
        :return:
        """
        for k, v in kwargs.items():
            if hasattr(self, k):
                setattr(self, k, v)
        self.save()
        return self
